package com.ptswitch.analyser.comm;

import java.io.BufferedOutputStream;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.io.UnsupportedEncodingException;
import java.net.InetSocketAddress;
import java.nio.BufferUnderflowException;
import java.nio.ByteBuffer;
import java.nio.CharBuffer;
import java.nio.channels.SelectionKey;
import java.nio.channels.Selector;
import java.nio.channels.SocketChannel;
import java.nio.charset.CharacterCodingException;
import java.nio.charset.Charset;
import java.nio.charset.CharsetEncoder;
import java.util.ArrayList;
import java.util.Date;
import java.util.Iterator;
import java.util.List;
import java.util.Timer;
import java.util.TimerTask;

import org.apache.commons.lang.StringUtils;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;

import com.ptswitch.analyser.AnalyserUtils;
import com.ptswitch.analyser.UIUtils;
import com.ptswitch.analyser.config.Configuration;
import com.ptswitch.analyser.config.SysParamters;
import com.ptswitch.analyser.db.ORMUtils;
import com.ptswitch.analyser.model.Station;

public class SocketCommunicator implements Communicater, SysParamters {

	private static final Log logger = LogFactory.getLog(SocketCommunicator.class);

	public static final String LOGIN_MSG = "PTSWITCH";

	public static final int CMD_EXECUTE_SUCC = 1;
	public static final int CHECK_ERROR_CODE = 69;

	public static final int ERROR_CODE_FATAL = 1;
	public static final int ERROR_CODE_WARNING = 2;

	public static final int GET_CAPTOR_INFO = 45;
	public static final int CAPTOR_INFO = 46;

	public static final int LOAD_SUBSTATION = 70;
	public static final int PARSE_PKT_FILE = 72;
	public static final int START_RT_ANALYSIS = 73;
	public static final int STOP_RT_ANALYSIS = 74;

	public static final int GET_NIC_LIST = 26;
	public static final int LIST_NIC_SUCC = 27;

	public static final int PRE_PARSE_PKT_FILE = 75;
	public static final int PRE_PARSE_PKT_FILE_SUCC = 76;

	public static final int ADJUST_SYS_PARAM = 78;

	public static final int QUERY_HISTORY_PACKET = 79;

	public static final int CMD_QUIT_SERVER = 180;

	public static final int GET_ENGINE_INFO = 80;
	public static final int ENGINE_INFO = 81;

	public static final int ADD_CID = 83;

	public static final int CLIENT_LOGIN = 91;
	public static final int CMD_CANCEL = 92;
	public static final int CMD_CANCEL_SUCC = 93;
	public static final int CMD_CANCEL_FAIL = 94;

	public static final int UPDATE_SYS_PARAM = 84;

	/** request : add network interface to network, and start to capture */
	public static final int ADD_NIC_TO_NET = 105;
	/** request :delete network interface from network, and stop to capture */
	public static final int DEL_NIC_FROM_NET = 106;
	/** request: get all network interfaces id owned by net */
	public static final int GET_NIC_OF_NET = 107;
	/** answer: all network interfaces id owned by net */
	public static final int NICS_OF_NET = 108;
	/**  */
	public static final int SUBSCRIBE_REAL_PACKET = 109;

	public static final int QUERY_PACKET = 200;
	public static final int QUERY_PACKET_RET = 201;
	public static final int QUERY_READ_PKT = 202;
	public static final int QUERY_READ_PKT_RET = 203;

	public static final int QUERY_INFO = 204;
	public static final int QUERY_INFO_RET = 205;

	public static final int SET_QUOTAL_LIMIT = 206;

	public static final int GET_FS_STATE = 208;

	public static final int FILE_PART_SIZE = 16 * 1024;// 32K大小

	InetSocketAddress serverIP;
	Selector selector;

	CharsetEncoder encoder = Charset.forName("UTF-8").newEncoder();

	Timer timer;

	public static final int TIMEOUT = 600000;// ms

	Station lastLoadedStation;
	private int lastReqSeq;
	private int lastReqCmd;
	private int lastResCmd;

	public void initSocket() throws IOException {
		SocketChannel client = SocketChannel.open();
		client.configureBlocking(false);
		selector = Selector.open();
		client.register(selector, SelectionKey.OP_CONNECT);
		String port = ORMUtils.getSysParamValue("COMM_CONFIG_PORT");
		if (StringUtils.isEmpty(port)) {
			port = "9006";
		}
		serverIP = new InetSocketAddress(Configuration.getServerIP(), Integer.valueOf(port));
		client.connect(serverIP);

		selector.select();
		Iterator<SelectionKey> iter = selector.selectedKeys().iterator();
		// System.out.println("selector.selectedKeys():" +
		// selector.selectedKeys().size());
		while (iter.hasNext()) {
			SelectionKey key = iter.next();
			iter.remove();
			if (key.isConnectable()) {
				SocketChannel channel = (SocketChannel) key.channel();
				if (channel.isConnectionPending()) {
					channel.finishConnect();
				}
				channel.write(stringBuffer(LOGIN_MSG));

				channel.register(selector, SelectionKey.OP_WRITE);
				break;
			}
			// 登录时服务器不做应答
			// else if(key.isReadable()){
			// ByteBuffer responseBuffer = ByteBuffer.allocate(1024);
			// SocketChannel channel = (SocketChannel) key.channel();
			// int count = channel.read(responseBuffer);
			//        			
			// responseBuffer.flip();
			// byte content[] = new byte[count];
			// responseBuffer.get(content);
			// System.out.println("LOGIN FROM SERVER:" + new String(content));
			// channel.register(selector, SelectionKey.OP_WRITE);
			// return;
			//        			
			// }
		}
	}

	private ByteBuffer stringBuffer(String content) {
		try {
			return encoder.encode(CharBuffer.wrap(content));
		} catch (CharacterCodingException e) {
			logger.error(e.getMessage(), e);
		}
		return null;
	}

	private ByteBuffer buildRequest(int cmd, ByteBuffer paramBuffer) {
		paramBuffer.flip();
		ByteBuffer reqBuffer = ByteBuffer.allocate(16 + paramBuffer.remaining());
		lastReqSeq = (int) new Date().getTime() / 1000;
		reqBuffer.putInt(lastReqSeq);// 当前时间的秒数作为命令序列号
		lastReqCmd = cmd;
		reqBuffer.putInt(cmd);
		reqBuffer.putInt(0);
		reqBuffer.putInt(paramBuffer.remaining());

		reqBuffer.put(paramBuffer);
		reqBuffer.flip();
		return reqBuffer;
	}

	private int safeGetInt(ByteBuffer buffer) throws CommunicationException {
		if (buffer.remaining() < 4) {
			throw new CommunicationException("服务器的响应错误");
		}
		return buffer.getInt();
	}

	private int parseResponse(ByteBuffer respBuffer) throws CommunicationException {
		return parseResponse(respBuffer, true);
	}

	// 解析没有正常返回参数的响应
	private int parseResponse(ByteBuffer respBuffer, boolean mustSucc) throws CommunicationException {
		try {
			respBuffer.getInt();// int seq =
			lastResCmd = respBuffer.getInt();
			respBuffer.getInt();// int reserve =
			int paramLen = respBuffer.getInt();
			// logger.debug("response cmd:" + lastResCmd + ",  param len:" +
			// paramLen + "; respBuffer limit:"
			// + respBuffer.limit());
			// 返回的cmd只可能为1 成功,69 失败并且带错误信息,0 失败
			if (lastResCmd == 1 && paramLen == 0) {
				// logger.debug("Command success executed");
			} else if (lastResCmd == 0) {// 没有任何消息的失败,不推荐服务器返回此错误码
				throw new CommunicationException("分析引擎不能执行此操作,错误码:0");
			} else if (lastResCmd == CHECK_ERROR_CODE) {
				if (paramLen != 0) {
					respBuffer.getInt();
					int errCode = respBuffer.getInt();
					int errMsgLen = respBuffer.getInt();
					byte[] errMsgArr = new byte[errMsgLen];
					respBuffer.get(errMsgArr);
					String errMsg = null;
					try {
						errMsg = new String(errMsgArr, "UTF-8");
					} catch (UnsupportedEncodingException e) {

					}
					if (errCode == ERROR_CODE_FATAL) {// 严重错误
						logger.error(errMsg);
						throw new CommunicationException("分析引擎不能执行当前的操作:" + errMsg);
					} else {// 部分成功
						logger.warn(errMsg);
						// throw new CommunicationException("不能执行当前的操作:" +
						// errMsg);
					}
				}
			} else if (mustSucc) {
				throw new CommunicationException("分析引擎返回不正确的命令:" + lastResCmd);
			}
			return lastResCmd;
		} catch (BufferUnderflowException e) {
			logger.error(e.getMessage(), e);
			throw new CommunicationException("系统异常,不能解析命令", e);
		}
	}

	private ByteBuffer requestAndWaitWithReconn(ByteBuffer reqBuffer) throws CommunicationException {
		// 不做重连服务器的动作
		ByteBuffer respBuffer = null;
		ByteBuffer reqBufDup = reqBuffer.duplicate();
		try {
			respBuffer = requestAndWait(reqBuffer);
		} catch (CommunicationException e) {
			// 不能连接到服务器,重试一次
			logger.warn("不能连接到报文分析引擎,重试中...");
			logger.error(e.getMessage(), e);
			if (lastLoadedStation != null) {
				login(1);
				loadStationImpl(lastLoadedStation, false, false);
				respBuffer = requestAndWait(reqBufDup);
			}

		}
		return respBuffer;

	}

	private ByteBuffer requestAndWait(ByteBuffer reqBuffer) throws CommunicationException {
		return requestAndWait(reqBuffer, false);
	}

	// for synchronized,fixmeh need?
	private transient Object lock = new Object();

	private ByteBuffer requestAndWait(ByteBuffer reqBuffer, boolean nowait) throws CommunicationException {
		if (lastReqCmd != CMD_CANCEL) {
			synchronized (lock) {
				// long startTime=System.currentTimeMillis();
				// ByteBuffer response=requestAndWait2(reqBuffer,nowait);
				// long endTime=System.currentTimeMillis();
				// logger.debug("request and wait use time(ms):"+(endTime-startTime)+",cmd:"+lastReqCmd);
				// return response;
				return requestAndWait2(reqBuffer, nowait);
			}
		} else {
			return requestAndWait2(reqBuffer, nowait);
		}
	}

	private ByteBuffer requestAndWait2(ByteBuffer reqBuffer, boolean nowait) throws CommunicationException {
		boolean first = true;
		int paramLen = 0;
		int totalRead = 0;
		ByteBuffer onceBuf = ByteBuffer.allocate(512 * 1024);// 512K
		try {
			while (true) {
				if (selector == null) {
					throw new CommunicationException("selector is null");
				}
				selector.select();
				Iterator<SelectionKey> iter = selector.selectedKeys().iterator();
				if (selector.selectedKeys().size() == 0) {
					throw new CommunicationException("发生超时,服务器在" + TIMEOUT / 1000 + "s内无响应," + UIUtils.serverInfo());
				}
				while (iter.hasNext()) {
					SelectionKey key = iter.next();
					iter.remove();
					if (key.isReadable()) {

						if (timer != null) {
							timer.cancel();
						}

						SocketChannel readChannel = (SocketChannel) key.channel();
						if (first) {
							onceBuf.clear();
						}
						int count = -1;
						while (count != 0) {
							count = readChannel.read(onceBuf);
							if (count == -1) {
								throw new IOException("Server closed count = -1");
							}
							totalRead += count;
							// logger.debug("channel.read count :" + count);
						}

						// onceBuf.flip();
						if (first) {
							ByteBuffer tmp = onceBuf.duplicate();
							tmp.flip();
							first = false;
							safeGetInt(tmp);// int seq =
							safeGetInt(tmp);// int cmd =
							safeGetInt(tmp);// int reserve =
							paramLen = safeGetInt(tmp);
							// logger.debug("preParse response: cmd:" + cmd +
							// ",param len:" + paramLen + ",total expect:" +
							// (paramLen + 16));
						}
						// logger.debug("total=" + totalRead);

						if (totalRead == paramLen + 16) {
							readChannel.register(selector, SelectionKey.OP_WRITE);
							onceBuf.flip();
							return onceBuf;
						}

					} else if (key.isWritable()) {
						// reqBuffer.flip();
						if (reqBuffer == null) {
							try {
								Thread.sleep(50);
							} catch (InterruptedException e) {
								logger.error(e.getMessage(), e);
							}
						} else {
							ByteBuffer tmp = reqBuffer.duplicate();
							int seq = tmp.getInt();
							int cmd = tmp.getInt();
							SocketChannel writeChannel = (SocketChannel) key.channel();
							writeChannel.write(reqBuffer);
							// logger.debug("request wrote(cmd:" + cmd + ",seq:"
							// + seq + "),waiting for server response...");
							reqBuffer = null;

							if (timer != null) {
								timer.cancel();
							}
							timer = new Timer("SockCommunicator");
							timer.schedule(new TimerTask() {

								@Override
								public void run() {
									selector.wakeup();
								}

							}, TIMEOUT);

							writeChannel.register(selector, SelectionKey.OP_READ | SelectionKey.OP_WRITE);
							if (nowait) {
								return null;
							}

						}

					}
				}
			}

		} catch (IOException e) {
			logger.error(e.getMessage(), e);
			throw new CommunicationException("不能连接到报文分析引擎" + UIUtils.serverInfo(), e);
		}
	}

	public void loadStation(Station station, boolean forceLoad) throws CommunicationException {

		// if(!forceLoad && station.equals(lastLoadedStation)){
		// return;
		// }
		lastLoadedStation = station;
		// logger.debug("loadStation() " + station.getName());

		loadStationImpl(station, true, forceLoad);
	}

	private void loadStationImpl(Station station, boolean reconnect, boolean forceLoad) throws CommunicationException {
		ByteBuffer paramBuffer = ByteBuffer.allocate(16);
		paramBuffer.putInt(4);
		paramBuffer.putInt(station.getLongId().intValue());
		paramBuffer.putInt(4);
		paramBuffer.putInt(forceLoad ? 1 : 0);

		ByteBuffer reqBuffer = buildRequest(LOAD_SUBSTATION, paramBuffer);
		ByteBuffer respBuffer;
		if (reconnect) {
			respBuffer = requestAndWaitWithReconn(reqBuffer);
		} else {
			respBuffer = requestAndWaitWithReconn(reqBuffer);
		}
		try {
			parseResponse(respBuffer);
		} catch (CommunicationException ex) {
			lastLoadedStation = null;
			throw ex;
		}
	}

	public void parsePKTFile(String[] pktFilepaths, int[] pktFileIDs, String startTime, String endTime)
			throws CommunicationException {
		int paramLen = 0;
		byte[] pathBytes = null;
		ByteBuffer paramBuf = null;
		// logger.debug("parse pkt,starttime=" + startTime);
		// logger.debug("parse pkt,endtime=" + endTime);
		try {
			for (String pktFilepath : pktFilepaths) {
				pathBytes = pktFilepath.getBytes("UTF-8");
				// logger.debug("parse pkt,filename :" + pktFilepath);
				paramLen += pathBytes.length;
				paramLen += 12;
			}

			paramLen += 8 + startTime.length() + endTime.length();

			paramBuf = ByteBuffer.allocate(paramLen);
			paramBuf.putInt(startTime.length());
			paramBuf.put(startTime.getBytes());

			paramBuf.putInt(endTime.length());
			paramBuf.put(endTime.getBytes());

			for (int i = 0; i < pktFilepaths.length; i++) {
				pathBytes = pktFilepaths[i].getBytes("UTF-8");
				paramBuf.putInt(pathBytes.length);
				paramBuf.put(pathBytes);
				paramBuf.putInt(4);
				paramBuf.putInt(pktFileIDs[i]);
			}
		} catch (UnsupportedEncodingException e) {
			logger.error(e.getMessage(), e);
			throw new CommunicationException("系统异常，不能发送解析PKT请求", e);
		}
		ByteBuffer reqBuffer = buildRequest(PARSE_PKT_FILE, paramBuf);

		ByteBuffer respBuffer = requestAndWaitWithReconn(reqBuffer);
		if (lastReqCmd == PARSE_PKT_FILE) {
			parseResponse(respBuffer);
		} else if (lastReqCmd == CMD_CANCEL) {
			while (parseResponse(respBuffer, false) != CMD_CANCEL_SUCC && lastResCmd != CMD_CANCEL_FAIL) {
				respBuffer = requestAndWait(null);
			}
		}
	}

	public PktFileAttribute preParsePKTFile(File pktFile) throws CommunicationException {
		int paramLen = 0;
		byte[] pathBytes = null;
		try {
			pathBytes = pktFile.getAbsolutePath().getBytes("UTF-8");
		} catch (UnsupportedEncodingException e) {
			logger.error(e.getMessage(), e);
			throw new CommunicationException("系统异常，不能发送PKT文件预解析请求", e);
		}
		paramLen += pathBytes.length;
		paramLen += 4;

		ByteBuffer paramBuf = ByteBuffer.allocate(paramLen);
		paramBuf.putInt(pathBytes.length);
		paramBuf.put(pathBytes);
		ByteBuffer reqBuf = buildRequest(PRE_PARSE_PKT_FILE, paramBuf);
		ByteBuffer respBuf = requestAndWaitWithReconn(reqBuf);
		PktFileAttribute fileAttr = new PktFileAttribute(pktFile);
		return preParsePktParseResponse(respBuf, fileAttr);
	}

	private PktFileAttribute preParsePktParseResponse(ByteBuffer respBuffer, PktFileAttribute fileAttr)
			throws CommunicationException {

		if (parseResponse(respBuffer, false) != PRE_PARSE_PKT_FILE_SUCC) {
			throw new CommunicationException("PKT文件预解析失败");
		}

		try {
			int argLen;
			byte[] argBuf;
			argLen = respBuffer.getInt();
			argBuf = new byte[argLen];
			respBuffer.get(argBuf);
			fileAttr.setStartTime(new String(argBuf));

			argLen = respBuffer.getInt();
			argBuf = new byte[argLen];
			respBuffer.get(argBuf);
			fileAttr.setEndTime(new String(argBuf));

			argLen = respBuffer.getInt();
			fileAttr.setTotalPackets(respBuffer.getInt());

			return fileAttr;
		} catch (BufferUnderflowException e) {
			throw new CommunicationException("系统异常,不能获取PKT文件属性", e);
		}
	}

	// cidIDS 是新增的CID的数据库ID,以逗号分隔 FIXME 要有返回值！
	public void addCid(String cidIDs) throws CommunicationException {
		byte[] byteArr = cidIDs.getBytes();
		int byteLen = byteArr.length;
		int paramLen = 4 + byteLen;
		ByteBuffer paramBuffer = ByteBuffer.allocate(paramLen);
		paramBuffer.putInt(byteLen); // 4 byte
		paramBuffer.put(byteArr);

		ByteBuffer reqBuffer = buildRequest(ADD_CID, paramBuffer);
		ByteBuffer respBuffer = requestAndWaitWithReconn(reqBuffer);
		parseResponse(respBuffer);
	}

	public List<String> listNIC() throws CommunicationException {

		ByteBuffer reqBuffer = ByteBuffer.allocate(16);
		reqBuffer.putInt((int) new Date().getTime() / 1000);// 当前时间的秒数作为命令序列号
		reqBuffer.putInt(GET_NIC_LIST);
		reqBuffer.putInt(0);
		reqBuffer.putInt(0);
		reqBuffer.flip();
		ByteBuffer respBuffer = requestAndWaitWithReconn(reqBuffer);

		if (parseResponse(respBuffer, false) != LIST_NIC_SUCC) {
			throw new CommunicationException("分析引擎不能获取网卡列表");
		}

		int remain = respBuffer.remaining();
		List<String> result = new ArrayList<String>();
		while (remain > 0) {
			result.add(parseNIC(respBuffer));
			remain = respBuffer.remaining();
		}

		return result;
	}

	// LENGTH(4 byte int),NIC1_ID(4 byte int),LENGTH(4 byte int),NIC1_NAME(...)
	private String parseNIC(ByteBuffer respBuffer) throws CommunicationException {
		StringBuilder sb = new StringBuilder();
		try {
			respBuffer.getInt();
			int nicID = respBuffer.getInt();// id, int
			sb.append(nicID);

			int nameLen = respBuffer.getInt();
			byte[] nic = new byte[nameLen];// name, byte array
			respBuffer.get(nic);
			String nicName = new String(nic, "UTF-8");
			// System.out.println("[NIC] ID:" + nicID + "  Name:" + nicName);
			sb.append(',').append(StringUtils.trim(nicName));

			return sb.toString();
		} catch (BufferUnderflowException e) {
			throw new CommunicationException("系统异常，不能获取网卡信息", e);
		} catch (UnsupportedEncodingException e) {
			throw new CommunicationException("系统异常，不能获取网卡信息", e);
		}
	}

	// ADD_NIC_TO_NET
	public boolean addNICtoNet(int nicID, int netID) throws CommunicationException {

		ByteBuffer reqBuffer = ByteBuffer.allocate(16 + 8 + 8); // extra 8+8 for
																// two int
																// params
		reqBuffer.putInt((int) new Date().getTime() / 1000);// sequence
		reqBuffer.putInt(ADD_NIC_TO_NET);// cmd
		reqBuffer.putInt(0); // reserved
		reqBuffer.putInt(8 + 8);
		reqBuffer.putInt(4); // one int for 4 byte
		reqBuffer.putInt(netID);// param1
		reqBuffer.putInt(4); // one int for 4 byte
		reqBuffer.putInt(nicID);// param2
		reqBuffer.flip();

		ByteBuffer respBuffer = requestAndWaitWithReconn(reqBuffer);

		if (parseResponse(respBuffer) == CMD_EXECUTE_SUCC) {
			return true;
		}

		return false;
	}

	// DEL_NIC_FROM_NET
	public boolean delNICfromNet(int nicID) throws CommunicationException {

		ByteBuffer reqBuffer = ByteBuffer.allocate(16 + 8);// extra 8 for one
															// int param
		reqBuffer.putInt((int) new Date().getTime() / 1000);// sequence
		reqBuffer.putInt(DEL_NIC_FROM_NET);// cmd
		reqBuffer.putInt(0);// reserved
		reqBuffer.putInt(8);// total param length
		reqBuffer.putInt(4);// one int for 4 byte
		reqBuffer.putInt(nicID);// param
		reqBuffer.flip();

		ByteBuffer respBuffer = requestAndWaitWithReconn(reqBuffer);

		if (parseResponse(respBuffer) == CMD_EXECUTE_SUCC) {
			return true;
		}

		return false;
	}

	// GET_NIC_OF_NET
	public List<Integer> getNICofNet(int netID) throws CommunicationException {

		ByteBuffer reqBuffer = ByteBuffer.allocate(16 + 8);
		reqBuffer.putInt((int) new Date().getTime() / 1000);
		reqBuffer.putInt(GET_NIC_OF_NET);
		reqBuffer.putInt(0);
		reqBuffer.putInt(8);// param length
		reqBuffer.putInt(4);// one int for 4 byte
		reqBuffer.putInt(netID);// param
		reqBuffer.flip();

		ByteBuffer respBuffer = requestAndWaitWithReconn(reqBuffer);

		List<Integer> nicList = new ArrayList<Integer>();
		if (parseResponse(respBuffer, false) == NICS_OF_NET) {
			int remain = respBuffer.remaining();

			while (remain >= 8) {
				respBuffer.getInt();// jump over the length field
				nicList.add(Integer.valueOf(respBuffer.getInt()));
				remain = respBuffer.remaining();
			}
		}

		return nicList;
	}

	/*
	 * netID: 网络ID iedList: 字符串,用户设置的需显示实时报文的IED逻辑设备名称(非IED名称),以逗号分隔 spanTime:
	 * 4字节,持续时间,值为1-3600
	 */
	public boolean subscribeRealPacket(String iedLDeviceList, int spanTime, int netID) throws CommunicationException {
		byte[] byteArr = iedLDeviceList.getBytes();
		int byteLen = byteArr.length;
		int paramLen = 8 + 8 + (4 + byteLen); // extra 4 bytes to store
												// byteLen's value, two 8 bytes
												// for each int

		ByteBuffer paramBuffer = ByteBuffer.allocate(paramLen);
		paramBuffer.putInt(4);
		paramBuffer.putInt(netID); // consumed 8
		paramBuffer.putInt(byteLen);
		paramBuffer.put(byteArr); // consumed 4 + byteLen
		paramBuffer.putInt(4);
		paramBuffer.putInt(spanTime); // consumed 8

		ByteBuffer reqBuffer = buildRequest(SUBSCRIBE_REAL_PACKET, paramBuffer);
		ByteBuffer respBuffer = requestAndWaitWithReconn(reqBuffer);

		if (parseResponse(respBuffer) == CMD_EXECUTE_SUCC) {
			return true;
		}
		return false;
	}

	public void login(int supervisor) throws CommunicationException {
		// if(selector != null){
		// return;
		// }

		try {
			initSocket();
		} catch (IOException e) {
			selector = null;
			logger.error(e.getMessage(), e);
			throw new CommunicationException("不能连接到报文分析引擎" + UIUtils.serverInfo(), e);
		}

		ByteBuffer paramBuffer = ByteBuffer.allocate(8);
		paramBuffer.putInt(4);
		paramBuffer.putInt(supervisor);
		ByteBuffer reqBuf = buildRequest(CLIENT_LOGIN, paramBuffer);
		ByteBuffer respBuffer = requestAndWaitWithReconn(reqBuf);
		parseResponse(respBuffer);
	}

	public void logout() throws CommunicationException {

		if (AnalyserUtils.isServerOnLocalhost()) {
			ByteBuffer paramBuffer = ByteBuffer.allocate(0);

			ByteBuffer reqBuffer = buildRequest(CMD_QUIT_SERVER, paramBuffer);
			// logger.debug("logout()");
			try {
				requestAndWaitWithReconn(reqBuffer);
			} catch (Exception e) {
				throw new CommunicationException("系统退出", e);
			}
		}

	}

	public List<String> listCaptureNIC(List<String> nicList) throws CommunicationException {
		List<String> result = new ArrayList<String>();
		for (String nic : nicList) {
			int utf8Len = 0;
			byte[] byteArr = null;
			try {
				byteArr = nic.getBytes("UTF-8");
				utf8Len = byteArr.length;
			} catch (UnsupportedEncodingException e) {
				logger.error(e.getMessage(), e);
			}

			ByteBuffer paramBuffer = ByteBuffer.allocate(4 + utf8Len);
			paramBuffer.putInt(utf8Len);
			paramBuffer.put(byteArr);

			ByteBuffer reqBuffer = buildRequest(GET_CAPTOR_INFO, paramBuffer);
			ByteBuffer respBuffer = requestAndWaitWithReconn(reqBuffer);

			if (parseResponse(respBuffer, false) != CAPTOR_INFO) {
				throw new CommunicationException("分析引擎不能获取网卡信息");
			}
			try {
				// logger.debug(nic + " info:");
				int argLen;
				byte[] argBuf;
				argLen = respBuffer.getInt();
				argBuf = new byte[argLen];
				respBuffer.get(argBuf);
				String status = "";
				status = new String(argBuf, "UTF-8");
				// logger.debug("Status:" + status);
				if ("0".equals(status)) {// 服务器正在通过此网卡抓包
					result.add(nic);
				}
				// ...其余的信息暂不关心

				argLen = respBuffer.getInt();
				argBuf = new byte[argLen];
				respBuffer.get(argBuf);
				String rule = "";
				rule = new String(argBuf, "UTF-8");
				// logger.debug("Rule:" + rule);

				argLen = respBuffer.getInt();
				long rate = respBuffer.getLong();
				// logger.debug("rate:" + rate);
			} catch (BufferUnderflowException e) {
				throw new CommunicationException("系统异常，不能获取网卡信息", e);
			} catch (UnsupportedEncodingException e) {
				throw new CommunicationException("系统异常，不能获取网卡信息", e);
			}
		}

		// logger.debug("Capturing NIC:" + result);
		return result;
	}

	public EngineInfo getEngineInfo() throws CommunicationException {
		ByteBuffer reqBuffer = buildRequest(GET_ENGINE_INFO, ByteBuffer.allocate(0));

		ByteBuffer respBuffer = requestAndWaitWithReconn(reqBuffer);

		if (parseResponse(respBuffer, false) != ENGINE_INFO) {
			throw new CommunicationException("分析引擎不能获取服务器信息");
		}
		try {
			EngineInfo engineInfo = new EngineInfo();
			int stationID;
			byte[] argBuf;
			respBuffer.getInt();
			stationID = respBuffer.getInt();
			engineInfo.setStationID(Long.valueOf(stationID));

			int argLen = respBuffer.getInt();
			argBuf = new byte[argLen];
			respBuffer.get(argBuf);
			String platform = "";
			platform = new String(argBuf, "UTF-8");
			engineInfo.setPlatform(platform);

			argLen = respBuffer.getInt();
			argBuf = new byte[argLen];
			respBuffer.get(argBuf);
			String version = "";
			version = new String(argBuf, "UTF-8");
			engineInfo.setEngineVersion(version);

			argLen = respBuffer.getInt();
			argBuf = new byte[argLen];
			respBuffer.get(argBuf);
			String limitInfo = "";
			limitInfo = new String(argBuf, "UTF-8");
			engineInfo.setLimitInfo(limitInfo);

			return engineInfo;
		} catch (BufferUnderflowException e) {
			throw new CommunicationException("系统异常，不能获取服务器信息", e);
		} catch (UnsupportedEncodingException e) {
			throw new CommunicationException("系统异常，不能获取服务器信息", e);
		}

	}

	public List<String> queryInfo(String netId) throws CommunicationException {
		ByteBuffer paramBuffer = ByteBuffer.allocate(8);
		paramBuffer.putInt(4);
		paramBuffer.putInt(Integer.valueOf(netId));

		ByteBuffer reqBuffer = buildRequest(QUERY_INFO, paramBuffer);
		ByteBuffer respBuffer = requestAndWaitWithReconn(reqBuffer);
		if (parseResponse(respBuffer, false) != QUERY_INFO_RET) {
			throw new CommunicationException("分析引擎不能获取可查询的报文类型和IED列表");
		}
		List<String> list = new ArrayList<String>();
		try {
			int tmpLen = respBuffer.getInt();
			byte[] tmpByte = new byte[tmpLen];
			respBuffer.get(tmpByte);
			String tmpString = new String(tmpByte, "UTF-8");
			list.add(tmpString);
			tmpLen = respBuffer.getInt();
			tmpByte = new byte[tmpLen];
			respBuffer.get(tmpByte);
			tmpString = new String(tmpByte, "UTF-8");
			list.add(tmpString);
		} catch (BufferUnderflowException e) {
			logger.debug(e.getMessage(), e);
			throw new CommunicationException("系统异常，不能获取可查询的报文类型和IED列表", e);
		} catch (UnsupportedEncodingException e) {
			logger.debug(e.getMessage(), e);
			throw new CommunicationException("系统异常，不能获取可查询的报文类型和IED列表", e);
		}
		return list;
	}

	public List<String> queryPacket(String netId, String ied, String packetType, String date, String time)
			throws CommunicationException {
		// logger.debug("query packet, netId:" + netId + "\nied:" + ied +
		// "\npacketType:" + packetType + "\n" + date + "\n" + time + "\n");
		ByteBuffer paramBuffer = ByteBuffer.allocate(20 + netId.length() + ied.length() + packetType.length()
				+ date.length() + time.length());
		paramBuffer.putInt(netId.length());
		paramBuffer.put(netId.getBytes());
		paramBuffer.putInt(ied.length());
		paramBuffer.put(ied.getBytes());
		paramBuffer.putInt(packetType.length());
		paramBuffer.put(packetType.getBytes());
		paramBuffer.putInt(date.length());
		paramBuffer.put(date.getBytes());
		paramBuffer.putInt(time.length());
		paramBuffer.put(time.getBytes());

		ByteBuffer reqBuffer = buildRequest(QUERY_PACKET, paramBuffer);
		ByteBuffer respBuffer = requestAndWaitWithReconn(reqBuffer);

		if (parseResponse(respBuffer, false) != QUERY_PACKET_RET) {
			throw new CommunicationException("分析引擎不能获取查询结果");
		}
		try {
			respBuffer.getInt();// int idLen =
			int id = respBuffer.getInt();
			respBuffer.getInt();// int countLen =
			int count = respBuffer.getInt();
			// logger.debug("query result count:" + count);
			List<String> filenames = new ArrayList<String>();
			filenames.add(String.valueOf(id));
			int filenameLen = 0;
			byte[] filenameBytes;
			for (int i = 0; i < count; i++) {
				filenameLen = respBuffer.getInt();
				// logger.debug("file " + i + "name Len :" + filenameLen);
				filenameBytes = new byte[filenameLen];
				respBuffer.get(filenameBytes);
				filenames.add(new String(filenameBytes, "utf-8"));
			}
			return filenames;
		} catch (BufferUnderflowException e) {
			throw new CommunicationException("系统异常，不能获取查询结果", e);
		} catch (UnsupportedEncodingException e) {
			throw new CommunicationException("系统异常，不能获取查询结果", e);
		}
	}

	private boolean stopReadPkt = false;

	public void setStopReadPkt(boolean b) {
		stopReadPkt = b;
	}

	public void queryReadPkt(int id, String filename, String savepath) throws CommunicationException {
		// long startTime=System.currentTimeMillis();
		// int totalLen=0;
		OutputStream out;
		// logger.debug("download pkt,filename :"+filename);
		String f = filename.replaceAll("[/\\\\]", "_");
		// logger.debug("download pkt,save filename :"+savepath+f);
		try {
			int eof = 0;
			ByteBuffer paramBuffer;
			out = /* new BufferedOutputStream( */new FileOutputStream(new File(savepath + f))/* ) */;
			for (int i = 0; eof == 0 && !stopReadPkt; i++) {
				paramBuffer = ByteBuffer.allocate(8 + 8 + 4 + filename.length());
				paramBuffer.putInt(4);
				paramBuffer.putInt(id);
				paramBuffer.putInt(4);
				paramBuffer.putInt(i);// blockNum
				paramBuffer.putInt(filename.length());
				paramBuffer.put(filename.getBytes());

				ByteBuffer reqBuffer = buildRequest(QUERY_READ_PKT, paramBuffer);
				ByteBuffer respBuffer = requestAndWaitWithReconn(reqBuffer);
				parseResponse(respBuffer, false);

				respBuffer.getInt();// eof len
				eof = respBuffer.getInt();
				int len = respBuffer.getInt();
				// totalLen+=len;
				// logger.debug("block num:"+i+",  data len:"+len);
				byte[] data = new byte[len];
				// logger.debug("respBuffer remaining:"+respBuffer.remaining());
				respBuffer.get(data);
				out.write(data);
			}
			out.close();
		} catch (BufferUnderflowException e) {
			throw new CommunicationException("系统异常，不能下载报文文件", e);
		} catch (IOException e) {
			logger.error(e.getMessage(), e);
			throw new CommunicationException("系统异常，不能保存报文文件", e);
		}
		// long endTime=System.currentTimeMillis();
		// long spanTime=endTime-startTime;
		// logger.debug("download use time(ms):"+spanTime);
		// logger.debug(",file size:"+totalLen);
	}

	public void updateSysParam(String[] sysParam) throws CommunicationException {
		int len = 4 * sysParam.length;
		byte[] pathBytes = null;
		try {
			for (String s : sysParam) {
				pathBytes = s.getBytes("UTF-8");// STOR_ROOT_CONFIG 中文保存路径
				len += pathBytes.length;
			}
		} catch (UnsupportedEncodingException e) {
			throw new CommunicationException("系统异常，不能发送系统参数设置请求", e);
		}
		ByteBuffer paramBuffer = ByteBuffer.allocate(len);
		try {
			for (String s : sysParam) {
				pathBytes = s.getBytes("UTF-8");
				paramBuffer.putInt(pathBytes.length);
				paramBuffer.put(pathBytes);
				// logger.debug(s);
			}
		} catch (UnsupportedEncodingException e) {
			throw new CommunicationException("系统异常，不能发送系统参数设置请求", e);
		}

		ByteBuffer reqBuffer = buildRequest(UPDATE_SYS_PARAM, paramBuffer);
		ByteBuffer respBuffer = requestAndWaitWithReconn(reqBuffer);
		parseResponse(respBuffer);
	}

	public void setQuotaLimit(String type, int softLimit, int hardLimit) throws CommunicationException {
		ByteBuffer paramBuffer = ByteBuffer.allocate(20 + type.length());
		paramBuffer.putInt(4);
		paramBuffer.putInt(softLimit);
		paramBuffer.putInt(4);
		paramBuffer.putInt(hardLimit);
		paramBuffer.putInt(type.length());
		paramBuffer.put(type.getBytes());
		// logger.debug("set quotal limit,type:"+type+",soft:"+softLimit+",hard:"+hardLimit);
		ByteBuffer reqBuffer = buildRequest(SET_QUOTAL_LIMIT, paramBuffer);
		ByteBuffer respBuffer = requestAndWaitWithReconn(reqBuffer);
		parseResponse(respBuffer);

	}

	public void cmdCancel() throws CommunicationException {
		ByteBuffer paramBuffer = ByteBuffer.allocate(16);
		paramBuffer.putInt(4);
		paramBuffer.putInt(lastReqCmd);
		paramBuffer.putInt(4);
		paramBuffer.putInt(lastReqSeq);
		// logger.debug("lastCmd:"+lastReqCmd+",lastSeq:"+lastReqSeq);
		ByteBuffer reqBuffer = buildRequest(CMD_CANCEL, paramBuffer);
		requestAndWait(reqBuffer, true);// ByteBuffer respBuffer =
	}

	public List<Integer> getListeningNets() throws CommunicationException {
		List<Integer> list = new ArrayList<Integer>();
		for (int i = 1; i < 11; i++) {
			if (CommunicaterPool.getCommunicater().getNICofNet(i).size() > 0) {
				list.add(i);
			}
		}
		return list;
	}

	public int[] getFsState() throws CommunicationException {
		ByteBuffer reqBuffer = ByteBuffer.allocate(16);
		reqBuffer.putInt((int) new Date().getTime() / 1000);
		reqBuffer.putInt(GET_FS_STATE);// cmd
		reqBuffer.putInt(0);// reserved
		reqBuffer.putInt(0);// total param length
		reqBuffer.flip();
		ByteBuffer respBuffer = requestAndWaitWithReconn(reqBuffer);
		if (parseResponse(respBuffer, false) != CMD_EXECUTE_SUCC) {
			throw new CommunicationException("分析引擎不能获取磁盘空间大小");
		}
		try {
			int[] space = new int[2];
			respBuffer.getInt();// int idLen =
			space[0] = respBuffer.getInt();
			respBuffer.getInt();// int countLen =
			space[1] = respBuffer.getInt();
			// System.out.println(space[0]+";"+space[1]);
			return space;
		} catch (BufferUnderflowException e) {
			throw new CommunicationException("系统异常，不能获取磁盘空间大小", e);
		}
	}

}